﻿HmJS.$Import('core.fx');

/*
---
name: Zoomer
version: 1.9.3-0
description: Class to show zoomed image inside original
license: MIT-Style License (http://mifjs.net/license.txt)
download: http://mootools.net/forge/p/zoomer
source: http://github.com/creaven/Zoomer

copyright: Anton Samoylov (http://mifjs.net)
authors: Anton Samoylov (http://mifjs.net)

requires: [Core/Class.Extras, Core/Element.Style, Core/Element.Dimensions, Core/Element.Event, Core/Fx.Tween]
provides: Zoomer
...
*/

HmJS.register('image.effect.Zoomer', function ($ns) {

	var Zoomer = new Class({

		Implements: [Options],

		options: {
			smooth: 6
		},

		initialize: function (element, options) {
			this.setOptions(options);
			this.small = document.id(element);
			if (!this.small.complete) {
				this.small.addEvent('load', function () {
					this.prepareSmall();
				} .bind(this));
			} else {
				this.prepareSmall();
			}
			var src = this.options.big || this.small.get('big');

			var styles = {
				position: 'absolute',
				top: 0,
				left: 0,
				opacity: 0,
				cursor: 'crosshair'
			};

			if (typeof src == 'string') {
				this.big = new Element('img', {
					src: src,
					styles: styles
				});
			} else {
				this.big = src;
				this.big.setStyles(styles);
			}

			if (!this.big.complete) {
				this.big.addEvent('load', function () {
					this.prepareBig();
				} .bind(this));
			} else {
				this.prepareBig();
			}
		},

		prepareSmall: function () {
			this.wrapper = new Element('div', { 'class': 'zoomer-wrapper' }).wraps(this.small);
			['margin', 'left', 'top', 'bottom', 'right', 'float', 'clear', 'border', 'padding'].each(function (p) {
				var style = this.small.getStyle(p);
				var dflt = 'auto';
				if (['float', 'clear', 'border'].contains(p)) {
					dflt = 'none';
				}
				if (p == 'padding') { dflt = '0'; }
				try {
					this.small.setStyle(p, dflt);
					this.wrapper.setStyle(p, style);
				} catch (e) { };
			}, this);
			this.wrapper.setStyles({
				width: this.small.offsetWidth,
				height: this.small.offsetHeight,
				position: 'relative',
				overflow: 'hidden'
			});
			this.smallSize = {
				width: this.small.width,
				height: this.small.height
			};
			if (this.bigPrepared) {
				this.ready();
			} else {
				this.smallPrepared = true;
			}
		},

		prepareBig: function () {
			this.bigSize = {
				width: this.big.width,
				height: this.big.height
			};
			if (this.smallPrepared) {
				this.ready();
			} else {
				this.bigPrepared = true;
			}
		},

		ready: function () {
			this.big.inject(this.wrapper);
			this.bigWrapper = new Element('div', {
				'class': 'zoomer-wrapper-big',
				styles: {
					position: 'absolute',
					overflow: 'hidden',
					top: this.small.getPosition().y - this.wrapper.getPosition().y - this.wrapper.getStyle('border-top-width').toInt(),
					left: this.small.getPosition().x - this.wrapper.getPosition().x - this.wrapper.getStyle('border-left-width').toInt(),
					width: this.small.offsetWidth,
					height: this.small.offsetHeight,
					background: 'url("' + this.small.getAttribute('src') + '")',
					zIndex: (this.small.getStyle('zIndex').toInt() || 0) + 1
				},
				events: {
					mouseenter: this.startZoom.bind(this),
					mouseleave: this.stopZoom.bind(this),
					mousemove: this.move.bind(this)
				}
			}).wraps(this.big);
		},

		move: function (event) {
			this.dstPos = event.page;
		},

		startZoom: function () {
			this.position = this.small.getPosition();

			this.ratio = {
				x: 1 - this.bigSize.width / this.smallSize.width,
				y: 1 - this.bigSize.height / this.smallSize.height
			};

			this.current = {
				left: this.big.getStyle('left').toInt(),
				top: this.big.getStyle('top').toInt()
			};

			this.timer = this.zoom.periodical(10, this);
			this.big.fade('in');
		},

		stopZoom: function () {
			clearInterval(this.timer);
			this.big.fade('out');
		},

		zoom: function () {
			if (!this.dstPos) { return; }

			var steps = this.options.smooth,
					_dstPos = this.dstPos,
					_position = this.position,
					_current = this.current;
			var dst = {
				left: parseInt((_dstPos.x - _position.x) * this.ratio.x, 10),
				top: parseInt((_dstPos.y - _position.y) * this.ratio.y, 10)
			};
			_current.left -= (_current.left - dst.left) / steps;
			_current.top -= (_current.top - dst.top) / steps;

			this.big.setStyles(_current);
		}

	});

	return Zoomer;
});
